package com.zmn.uac.api.controllers.oauth.login;

import com.alibaba.fastjson.JSONObject;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.uac.api.constant.HeaderParamKeyConst;
import com.zmn.uac.business.enums.ThirdInfoEnum;
import com.zmn.uac.business.interfaces.oauth.login.LoginBaseBService;
import com.zmn.uac.business.interfaces.oauth.login.MobileCaptchaLoginBService;
import com.zmn.uac.business.interfaces.oauth.login.MobileLoginBService;
import com.zmn.uac.client.CaptchaClient;
import com.zmn.uac.common.dict.ErrorCodeDict;
import com.zmn.uac.common.dio.oauth.login.UserAuthLoginDIO;
import com.zmn.uac.common.dro.oauth.login.TokenAndUserInfoDRO;
import com.zmn.uac.common.dro.oauth.login.UserAuthLoginDRO;
import com.zmn.uac.common.dro.oauth.login.UserInfoDRO;
import com.zmn.uac.common.info.AuthLoginCode;
import com.zmn.uac.common.info.UserAuthPhoneInfo;
import com.zmn.uac.common.info.bytebeat.ByteBeatAuthPhoneInfo;
import com.zmn.uac.common.info.mobile.*;
import com.zmn.uac.util.LogAlibabaUtil;
import com.zmn.uuc.common.constant.CaptchaConsts;
import com.zmn.uuc.common.dio.captcha.SendCaptchaDIO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.Objects;
import java.util.Optional;

/**
 * 类描述：手机号验证码登录
 *
 * @author xujie
 * @since 2021/06/14 13:39
 */
@Api(tags = "手机号验证码登录")
@Slf4j
@RestController
@RequestMapping("/mobile")
public class MobileLoginController extends LoginBaseController {

    private static final String TAG = "手机号验证码登录";

    @Resource
    MobileLoginBService mobileLoginBusinessService;

    @Resource
    MobileCaptchaLoginBService mobileCaptchaLoginBusinessService;

    @Resource
    CaptchaClient captchaClient;

    /**
     * 发送手机验证码
     *
     * @param sendCaptcha sendCaptcha
     * @return ResponseDTO<UserAuthLoginDRO>
     * @author xujie
     * @since 2021/06/14
     */
    @ApiOperation(value = "发送手机验证码")
    @PostMapping(value = "/sendCaptcha",produces = MediaType.APPLICATION_JSON_VALUE, headers = {HeaderParamKeyConst.PLAT_ID_KEY})
    public ResponseDTO<Boolean> sendCaptcha(HttpServletRequest request,
                                            @RequestBody @Valid
                                            @NotNull(message = "手机号发送验证码不能为null") SendCaptcha sendCaptcha) {

        Integer platId = Integer.valueOf(Optional.ofNullable(request.getHeader(HeaderParamKeyConst.PLAT_ID_KEY)).orElse("0"));
        SendCaptchaDIO captcha = new SendCaptchaDIO();
        captcha.setPlat(platId);
        captcha.setMobile(sendCaptcha.getMobile());
        captcha.setType(CaptchaConsts.CAPTCHA_TYPE_USER_REGISTER_LOGIN);
        captcha.setCaptchaLength(4);
        Boolean sendStatus = captchaClient.sendCaptcha(captcha);

        return new ResponseDTO<>(sendStatus);
    }

    /**
     * 发送手机验证码
     *
     * @param captchaType
     * @return ResponseDTO<UserAuthLoginDRO>
     * @author xujie
     * @since 2021/06/14
     */
    @ApiOperation(value = "发送手机验证码")
    @PostMapping(value = "/sendCaptchaWithType", produces = MediaType.APPLICATION_JSON_VALUE, headers = {HeaderParamKeyConst.PLAT_ID_KEY})
    public ResponseDTO<Boolean> sendCaptchaWithType(HttpServletRequest request,
                                                    @RequestBody @Valid
                                                    @NotNull(message = "手机号发送验证码不能为null") CaptchaType captchaType) {

        Integer platId = Integer.valueOf(Optional.ofNullable(request.getHeader(HeaderParamKeyConst.PLAT_ID_KEY)).orElse("0"));
        SendCaptchaDIO captcha = new SendCaptchaDIO();
        captcha.setPlat(platId);
        captcha.setMobile(captchaType.getMobile());
        captcha.setType(captchaType.getType());
        captcha.setCaptchaLength(4);
        Boolean sendStatus = captchaClient.sendCaptcha(captcha);

        return new ResponseDTO<>(sendStatus);
    }

    /**
     * 用户手机号验证码登录、注册
     *
     * @param mobileCaptchaUserLoginInfo mobileCaptchaUserLoginInfo
     * @return ResponseDTO<UserAuthLoginDRO>
     * @author xujie
     * @since 2021/06/14
     */
    @ApiOperation(value = "用户手机号验证码登录、注册")
    @PostMapping(value = "/captcha/loginOrRegister",produces = MediaType.APPLICATION_JSON_VALUE, headers = {HeaderParamKeyConst.PLAT_ID_KEY, HeaderParamKeyConst.CHANNEL_ID_KEY})
    public ResponseDTO<UserAuthLoginDRO> captchaLoginOrRegister(HttpServletRequest request,
                                                                @RequestBody @Valid
                                                                @NotNull(message = "用户手机号验证码登录信息不能为null") MobileCaptchaUserLoginInfo mobileCaptchaUserLoginInfo) {

        UserAuthLoginDIO dio = getUserAuthLogin(request, "", mobileCaptchaUserLoginInfo.getEntrance());
        if (Objects.isNull(dio.getChannelId())) {
            return ResponseDTO.fail(ErrorCodeDict.ERROR_CODE_PARAM_NULL, "渠道ID不能为空!");
        }
        String uuid = dio.getUuid();
        log.info("[{}], {}, 用户手机号验证码登录、注册调用参数:{},{}", TAG, uuid, dio,mobileCaptchaUserLoginInfo);
        ResponseDTO<UserAuthLoginDRO> responseDTO = mobileCaptchaLoginBusinessService.login(dio, mobileCaptchaUserLoginInfo);
        log.info("[{}], {}, 用户手机号验证码登录、注册调用响应responseDTO:{}", TAG, uuid, responseDTO);
        UserAuthLoginDRO dro = responseDTO.getData();
        if (Objects.nonNull(dro)) {
            log.info("[{}], {}, 用户手机号验证码登录、注册成功，响应UserAuthLoginDRO:{}", TAG, uuid, dro);
            return ResponseDTO.success(dro);
        }
        log.error("[{}], {}, 用户手机号验证码登录、注册失败, msg:{}", TAG, uuid, responseDTO.getMessage());
        return ResponseDTO.fail(responseDTO.getMessage());
    }

    /**
     * 用户手机号验证码、三方openId登录、注册
     *
     * @param mobileCaptchaThirdOpenidUserLoginInfo mobileCaptchaThirdOpenidUserLoginInfo
     * @return ResponseDTO<UserAuthLoginDRO>
     * @author xujie
     * @since 2021/06/14
     */
    @ApiOperation(value = "用户手机号验证码、三方openId登录、注册")
    @PostMapping(value = "/captchaAndThirdOpenid/loginOrRegister",produces = MediaType.APPLICATION_JSON_VALUE, headers = {HeaderParamKeyConst.PLAT_ID_KEY, HeaderParamKeyConst.CHANNEL_ID_KEY, HeaderParamKeyConst.PROVINCE_ID_KEY, HeaderParamKeyConst.CITY_ID_KEY, HeaderParamKeyConst.PROVINCE_NAME_KEY, HeaderParamKeyConst.CITY_NAME_KEY})
    public ResponseDTO<UserAuthLoginDRO> captchaAndThirdOpenidLoginOrRegister(HttpServletRequest request,
                                                                              @RequestBody @Valid
                                                                              @NotNull(message = "用户手机号验证码、三方openId登录信息不能为null") MobileCaptchaThirdOpenidUserLoginInfo mobileCaptchaThirdOpenidUserLoginInfo) {

        UserAuthLoginDIO dio = getUserAuthLogin(request, mobileCaptchaThirdOpenidUserLoginInfo.getCode(), mobileCaptchaThirdOpenidUserLoginInfo.getEntrance());
        ResponseDTO<Boolean> validateCaptcha = validateCaptcha(dio.getPlat(), mobileCaptchaThirdOpenidUserLoginInfo.getMobile(), mobileCaptchaThirdOpenidUserLoginInfo.getCaptcha());
        if (!validateCaptcha.isSuccess()) {
            return ResponseDTO.fail(validateCaptcha.getMessage());
        }
        LoginBaseBService loginBaseBusinessService;
        try {
            loginBaseBusinessService = ThirdInfoEnum.getLoginBaseBService(mobileCaptchaThirdOpenidUserLoginInfo.getThirdType());
        } catch (Exception e) {
            log.error("[{}]，获取登录模板模式基类异常，参数：{}：msg: {}", TAG, JSONObject.toJSONString(mobileCaptchaThirdOpenidUserLoginInfo), e.getMessage(), e);
            return ResponseDTO.fail(e.getMessage());
        }
        String uuid = dio.getUuid();
        UserAuthPhoneInfo authPhoneInfo = ThirdInfoEnum.getUserAuthPhoneInfoClazz(mobileCaptchaThirdOpenidUserLoginInfo.getThirdType());
        ((AuthLoginCode) authPhoneInfo).setCode(mobileCaptchaThirdOpenidUserLoginInfo.getCode());
        authPhoneInfo.setMobile(mobileCaptchaThirdOpenidUserLoginInfo.getMobile());
        String thirdName = ThirdInfoEnum.getThirdName(mobileCaptchaThirdOpenidUserLoginInfo.getThirdType());
        if (StringUtil.isNotBlank(mobileCaptchaThirdOpenidUserLoginInfo.getAnonymousCode()) && ThirdInfoEnum.BYTE_BEAT.getThirdType().equals(mobileCaptchaThirdOpenidUserLoginInfo.getThirdType())) {
            ((ByteBeatAuthPhoneInfo) authPhoneInfo).setAnonymousCode(mobileCaptchaThirdOpenidUserLoginInfo.getAnonymousCode());
        }
        log.info("[{}], {}, {}用户手机号验证码、三方openId登录、注册调用参数:{},mobileCaptchaThirdOpenidUserLoginInfo={}", uuid, TAG, thirdName, dio,mobileCaptchaThirdOpenidUserLoginInfo);
        ResponseDTO<UserAuthLoginDRO> responseDTO = loginBaseBusinessService.login(dio, authPhoneInfo);
        log.info("[{}], {}, {}用户手机号验证码、三方openId登录、注册调用响应responseDTO:{}", TAG, uuid, thirdName, responseDTO);
        UserAuthLoginDRO dro = responseDTO.getData();
        if (Objects.nonNull(dro)) {
            log.info("[{}], {}, {}用户手机号验证码、三方openId登录、注册成功，响应UserAuthLoginDRO:{}", TAG, uuid, thirdName, dro);
            return ResponseDTO.success(dro);
        }
        log.error("[{}], {}, {}用户手机号验证码、三方openId登录、注册失败, msg:{}", TAG, uuid, thirdName, responseDTO.getMessage());
        return ResponseDTO.fail(responseDTO.getMessage());
    }

    /**
     * 用户手机号一键授权登录、注册
     *
     * @param authInfo authInfo
     * @return ResponseDTO<UserAuthLoginDRO>
     * @author xujie
     * @since 2021/06/14
     */
    @ApiOperation(value = "用户手机号一键授权登录、注册")
    @RequestMapping(value = "/loginOrRegister", method = {RequestMethod.POST}, produces = MediaType.APPLICATION_JSON_VALUE, headers = {HeaderParamKeyConst.PLAT_ID_KEY, HeaderParamKeyConst.CHANNEL_ID_KEY})
    public ResponseDTO<UserAuthLoginDRO> loginOrRegister(HttpServletRequest request,
                                                         @RequestBody @Valid
                                                         @NotNull(message = "用户手机号一键授权登录、注册信息不能为null") MobileUserAuthInfo authInfo) {

        UserAuthLoginDIO dio = getUserAuthLogin(request, "", authInfo.getEntrance());
        if (Objects.isNull(dio.getChannelId())) {
            return ResponseDTO.fail(ErrorCodeDict.ERROR_CODE_PARAM_NULL, "渠道ID不能为空!");
        }
        String uuid = dio.getUuid();
        log.info("[{}], {}, 用户手机号一键授权登录、注册调用参数:{}", TAG, uuid, dio);
        ResponseDTO<UserAuthLoginDRO> responseDTO = mobileLoginBusinessService.login(dio, authInfo);
        log.info("[{}], {}, 用户手机号一键授权登录、注册调用响应responseDTO:{}", TAG, uuid, responseDTO);
        UserAuthLoginDRO dro = responseDTO.getData();
        if (Objects.nonNull(dro)) {
            log.info("[{}], {}, 用户手机号一键授权登录、注册成功，响应UserAuthLoginDRO:{}", TAG, uuid, dro);
            UserAuthLoginDRO userAuthLoginDRO = responseDTO.getData();
            if (userAuthLoginDRO != null) {
                LogAlibabaUtil.loginLog(dio, userAuthLoginDRO, authInfo.getDeviceId());
            }
            return ResponseDTO.success(dro);
        }
        log.error("[{}], {}, 用户手机号一键授权登录、注册失败, msg:{}", TAG, uuid, responseDTO.getMessage());
        return ResponseDTO.fail(responseDTO.getMessage());
    }

    /**
     * 根据手机号和验证码登录
     * @param dio
     * @return
     */
    @ApiOperation(value = "根据手机号和验证码登录")
    @PostMapping("/login")
    public ResponseDTO login(@RequestBody @Valid MobileCaptchaUserLoginInfo dio,HttpServletRequest request){
        UserAuthLoginDIO authLogin = getUserAuthLogin(request, null, null);
        ResponseDTO responseDTO = mobileCaptchaLoginBusinessService.loginByMobileCaptcha(dio.getMobile(), dio.getCaptcha());
        log.info("[{}],根据手机号和验证码登录,手机号登录调用响应responseDTO:{},dio={}", TAG, responseDTO,dio);

        Object data = responseDTO.getData();

        if (data instanceof TokenAndUserInfoDRO) {
            UserInfoDRO userInfo = ((TokenAndUserInfoDRO) data).getUserInfo();
            if (userInfo != null) {
                LogAlibabaUtil.loginLog(userInfo, authLogin, dio.getDeviceId());
            }
        }

        if (Objects.nonNull(data)) {
            log.info("[{}],通过手机号用户登录成功，响应responseDTO:{}", TAG, data);
            return ResponseDTO.success(data);
        }

        log.error("[{}],通过手机号用户登录失败, msg:{}", TAG, responseDTO.getMessage());
        return responseDTO;
    }


    /**
     * 根据token退出登录
     * @param token
     * @return
     */
    @ApiOperation(value = "根据token退出登录")
    @GetMapping("/logOut")
    public ResponseDTO<Boolean> logOut(@RequestParam("token") @NotNull(message = "token不能为空") String token){
        ResponseDTO<Boolean> responseDTO = mobileCaptchaLoginBusinessService.logout(token);
        log.info("[{}],通过手机号登出调用响应responseDTO:{}", TAG, responseDTO);

        Boolean logOut = responseDTO.getData();
        if(Objects.nonNull(logOut)){
            log.info("[{}],通过手机号用户登出成功，响应responseDTO:{}", TAG, token);
            return ResponseDTO.success(logOut);
        }

        log.error("[{}],通过手机号用户登出失败，msg：{}",TAG,responseDTO.getMessage());
        return ResponseDTO.fail(responseDTO.getMessage());
    }



    /**
     * 根据Token获取用户信息
     * @param token
     * @return
     */
    @GetMapping("/getUserInfoByToken")
    public ResponseDTO<UserInfoDRO> getUserInfoByToken(@RequestParam("token") @NotNull(message = "token不能为空") String token){
        ResponseDTO<UserInfoDRO> responseDTO = mobileCaptchaLoginBusinessService.getUserInfoByToken(token);
        log.info("[{}],通过Token获取用户信息响应responseDTO:{}", TAG, responseDTO);

        UserInfoDRO data = responseDTO.getData();
        if(Objects.nonNull(data)){
            log.info("[{}],通过Token获取用户信息，响应responseDTO:{}", TAG, data);
            return ResponseDTO.success(data);
        }

        log.error("[{}],通过Token获取用户信息失败，msg：{}",TAG,responseDTO.getMessage());
        return ResponseDTO.fail(responseDTO.getMessage());
    }
}
